import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, messagebox

class ClipboardClient:
    def __init__(self, master):
        self.master = master
        self.master.title("给点知识-网络粘贴板客户端")

        # 输入框以指定服务器 IP 和端口
        self.ip_label = tk.Label(master, text="服务器 IP 地址:", font=("Arial", 12))
        self.ip_label.pack(pady=5)
        self.ip_entry = tk.Entry(master, width=20)
        self.ip_entry.pack(pady=5)
        self.ip_entry.insert(0, "127.0.0.1")  # 默认 IP

        self.port_label = tk.Label(master, text="服务器 端口:", font=("Arial", 12))
        self.port_label.pack(pady=5)
        self.port_entry = tk.Entry(master, width=20)
        self.port_entry.pack(pady=5)
        self.port_entry.insert(0, "9999")  # 默认端口

        # 连接服务器按钮
        self.connect_button = tk.Button(master, text="连接服务器", command=self.connect_to_server)
        self.connect_button.pack(pady=10)

        # 文本框显示接收到的消息
        self.text_area = scrolledtext.ScrolledText(master, wrap=tk.WORD, width=50, height=15, bg="white", fg="black")
        self.text_area.pack(pady=10, fill=tk.BOTH, expand=True)

        # 输入框以输入要发送的消息（使用 Text 小部件）
        self.entry_label = tk.Label(master, text="输入要发送的消息:", font=("Arial", 12))
        self.entry_label.pack(pady=5)
        
        self.message_frame = tk.Frame(master)
        self.message_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        self.message_entry = tk.Text(self.message_frame, wrap=tk.WORD, height=5,width=5)
        self.message_entry.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        self.send_button = tk.Button(self.message_frame, text="发送", command=self.send_message)
        self.send_button.pack(side=tk.RIGHT)

        self.client_socket = None

        # 绑定回车键发送消息
        self.message_entry.bind("<Return>", self.send_message_event)
        self.master.geometry("500x500")

    def connect_to_server(self):
        ip = self.ip_entry.get()
        try:
            port = int(self.port_entry.get())
            if not (1024 <= port <= 65535):
                raise ValueError("端口必须在 1024 到 65535 之间")
        except ValueError as e:
            messagebox.showerror("错误", f"无效的端口: {e}")
            return

        # 创建客户端 socket
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.client_socket.connect((ip, port))
            self.text_area.insert(tk.END, f"成功连接到服务器 {ip}:{port}\n", 'info')
            threading.Thread(target=self.receive_messages, daemon=True).start()
        except Exception as e:
            messagebox.showerror("错误", f"无法连接到服务器: {e}")

    def receive_messages(self):
        while True:
            try:
                message = self.client_socket.recv(1024).decode('utf-8')
                if message:
                    self.text_area.insert(tk.END, f"------------新消息--------------: \n{message}\n--------------------\n", 'received')
                    self.text_area.see(tk.END)  # 保持显示在最后
                else:
                    break
            except Exception as e:
                self.text_area.insert(tk.END, f"接收错误: {str(e)}\n", 'error')
                break

        self.client_socket.close()

    def send_message(self):
        message = self.message_entry.get("1.0", tk.END).strip()  # 获取 Text 小部件的内容
        if message:  # 发送消息前检查非空
            try:
                self.client_socket.send(message.encode('utf-8'))
                self.text_area.insert(tk.END, f"发送: {message}\n", 'sent')  # 在文本框中显示发送的消息
                self.message_entry.delete("1.0", tk.END)  # 清空输入框
            except Exception as e:
                self.text_area.insert(tk.END, f"发送错误: {str(e)}\n", 'error')

    def send_message_event(self, event):
        self.send_message()

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("600x400")  # 设置初始窗口大小

    # 创建标签和文本框的样式
    style = tk.Text(root)
    style.tag_configure('sent', foreground='blue')
    style.tag_configure('received', foreground='green')
    style.tag_configure('info', foreground='black')
    style.tag_configure('error', foreground='red')

    client = ClipboardClient(root)
    root.mainloop()